namespace grflib { namespace engine { namespace core {

    //////////////////////////////////////////////////////
    //Implementation of singleton manager basis class
    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::_CManagerBaseSingle() {}

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::~_CManagerBaseSingle()
    {
        Clear();
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    TMan *_CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::Instance()
    {
        static TMan sceneManager;
        return &sceneManager;
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    bool _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::AddObj(const TKey &name, TPtr &pObj)
    {
        if (m_store.find(name) != m_store.end())
        {
            W32ERR(_T("Object of the same name already exists in scene!"));
            return false;
        }
        m_store[name] = pObj;
        return true;
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    void _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::RemoveObj(const TKey &name)
    {
        obj_iter_type iter = m_store.find(name);
        if (iter != m_store.end())
        {
            (iter->second).reset();
            m_store.erase(iter);
        }
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    TPtr & _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::FindObj(const TKey &name)
    {
        obj_iter_type iter = m_store.find(name);
        static TPtr empty;
        if (iter == m_store.end())
            return empty;
        else
            return iter->second;
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    TPtr & _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::operator[](const TKey &name)
    {
        return m_store[name];
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    HRESULT _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::Traverse(const IMemberCaller<TObj> &func)
    {
        HRESULT hr = S_OK;
        BOOST_FOREACH(obj_ref_type rObj, m_store)
        {
            V_RETURN( func(rObj.second) );
        }
        return hr;
    }

    template<typename TMan, typename TObj, int TId, typename TKey, typename TPtr>
    void _CManagerBaseSingle<TMan, TObj, TId, TKey, TPtr>::Clear()
    {
        IDeleteFunc<TObj> delFunc;
        Traverse(delFunc);
        m_store.clear();
    }

    //////////////////////////////////////////////////////
    //Implementation of instantiable manager basis class
    template<typename TObj, typename TKey, typename TPtr>
    _CManagerBase<TObj, TKey, TPtr>::_CManagerBase()
    {}

    template<typename TObj, typename TKey, typename TPtr>
    _CManagerBase<TObj, TKey, TPtr>::~_CManagerBase()
    { Clear(); }

    template<typename TObj, typename TKey, typename TPtr>
    bool _CManagerBase<TObj, TKey, TPtr>::AddObj(const TKey &name, TPtr &pObj)
    {
        if (m_store.find(name) != m_store.end())
        {
            W32ERR(_T("Object of the same name already exists in scene!"));
            return false;
        }
        m_store[name] = pObj;
        return true;
    }

    template<typename TObj, typename TKey, typename TPtr>
    void _CManagerBase<TObj, TKey, TPtr>::RemoveObj(const TKey &name)
    {
        obj_iter_type iter = m_store.find(name);
        if (iter != m_store.end())
        {
            (iter->second).reset();
            m_store.erase(iter);
        }
    }

    template<typename TObj, typename TKey, typename TPtr>
    TPtr & _CManagerBase<TObj, TKey, TPtr>::FindObj(const TKey &name)
    {
        obj_iter_type iter = m_store.find(name);
        static TPtr empty;
        if (iter == m_store.end())
            return empty;
        else
            return iter->second;
    }

    template<typename TObj, typename TKey, typename TPtr>
    bool _CManagerBase<TObj, TKey, TPtr>::GetObjName(TKey &name, const TPtr &pObj)
    {
        for (obj_iter_type iter = m_store.begin(); iter != m_store.end(); ++iter)
        {
            if (iter->second == pObj)
            {
                name = iter->first;
                return true;
            }
        }
        return false;
    }

    template<typename TObj, typename TKey, typename TPtr>
    TPtr & _CManagerBase<TObj, TKey, TPtr>::operator[](const TKey &name)
    {
        return m_store[name];
    }

    template<typename TObj, typename TKey, typename TPtr>
    HRESULT _CManagerBase<TObj, TKey, TPtr>::Traverse(const IMemberCaller<TObj> &func)
    {
        HRESULT hr = S_OK;
        BOOST_FOREACH(obj_ref_type rObj, m_store)
        {
            V_RETURN( func(rObj.second) );
        }
        return hr;
    }

    template<typename TObj, typename TKey, typename TPtr>
    HRESULT _CManagerBase<TObj, TKey, TPtr>::AbortableTraverse(const IMemberCaller<TObj> &func)
    {
        HRESULT hr = S_OK;
        BOOST_FOREACH(obj_ref_type rObj, m_store)
        {
            hr = func(rObj.second);
            if (hr == E_ABORT)
                break;
            V_RETURN(hr);
        }
        return hr;
    }

    template<typename TObj, typename TKey, typename TPtr>
    void _CManagerBase<TObj, TKey, TPtr>::Clear()
    {
        IDeleteFunc<TObj> delFunc;
        Traverse(delFunc);
        m_store.clear();
    }
}}} // namespaces
